package com.travel.task;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.travel.entity.po.Remind;
import com.travel.entity.po.TravelPlan;
import com.travel.entity.po.User;
import com.travel.mapper.RemindMapper;
import com.travel.mapper.TravelPlanMapper;
import com.travel.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class TravelTask {

    @Autowired
    TravelPlanMapper travelPlanMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    RemindMapper remindMapper;

    public static final String apiUrl = "https://api.dify.ai/v1/workflows/run";
    public static final String apiKey = "app-t4hAwiGrIlER1otLLZFJHXiu";


    @Scheduled(cron = "0 0 8 * * ?") // 每天早上8点执行/
//    @Scheduled(cron = "0 * * * * ?")// 每两分钟执行一次
//    @Scheduled(cron = "0 */2 * * * ?") // 每两分钟执行一次
    public void processTravelReminders() {
        log.info("旅行提醒任务执行，当前时间：{}", LocalDateTime.now());

        List<TravelPlan> travelPlans = travelPlanMapper.selectList(null);
        Date now = new Date();

        for (TravelPlan travelPlan : travelPlans) {
            log.info("当前旅行计划 + {}" , travelPlan );
            if (now.after(travelPlan.getCreateTime()) && now.before(travelPlan.getEndTime())) {
                try {
                    String reminderContent = createRemind(travelPlan);
                    log.info("API返回的提醒内容: {}", reminderContent);
                    
                    // 解析API响应 - 修改解析逻辑以适应workflows API的响应格式
                    JSONObject responseJson = JSONObject.parseObject(reminderContent);
                    
                    // workflows API响应格式：data -> outputs -> text
                    String content = null;
                    if (responseJson.containsKey("data")) {
                        JSONObject data = responseJson.getJSONObject("data");
                        if (data != null && data.containsKey("outputs")) {
                            JSONObject outputs = data.getJSONObject("outputs");
                            if (outputs != null && outputs.containsKey("text")) {
                                content = outputs.getString("text");
                                
                                // 如果内容被包裹在markdown代码块中，移除这些标记
                                if (content != null && content.startsWith("```") && content.endsWith("```")) {
                                    // 提取代码块内容
                                    int startIndex = content.indexOf("\n");
                                    int endIndex = content.lastIndexOf("```");
                                    if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) {
                                        content = content.substring(startIndex + 1, endIndex).trim();
                                    }
                                }
                            }
                        }
                    }
                    
                    // 如果找不到这个路径，尝试之前的格式
                    if (content == null) {
                        content = responseJson.getString("answer");
                    }

                    if (content != null && !content.isEmpty()) {
                        // 保存提醒到数据库
                        saveRemindToDatabase(travelPlan, content);
                        log.info("成功保存旅行提醒，计划ID: {}, 用户: {}", travelPlan.getId(), travelPlan.getUsername());
                    } else {
                        log.warn("API返回的提醒内容为空，计划ID: {}", travelPlan.getId());
                    }
                } catch (Exception e) {
                    log.error("为旅行计划[{}]创建提醒失败: {}", travelPlan.getId(), e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 将提醒内容保存到数据库
     *
     * @param travelPlan 旅行计划
     * @param content 提醒内容
     */
    private void saveRemindToDatabase(TravelPlan travelPlan, String content) {
        try {
            // 查询用户ID
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("username", travelPlan.getUsername());
            User user = userMapper.selectOne(userQueryWrapper);
            if (user == null) {
                log.error("未找到用户: {}", travelPlan.getUsername());
                return;
            }

            // 创建提醒对象
            Remind remind = new Remind();
            remind.setUserId(user.getId().intValue()); // 将Long转为Integer
            remind.setContent(content);
            remind.setTime(LocalDate.now());

            // 保存到数据库
            remindMapper.insert(remind);
            log.info("提醒已保存至数据库, ID: {}", remind.getId());
        } catch (Exception e) {
            log.error("保存提醒到数据库失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 创建旅行提醒 - 仅发送API请求部分
     *
     * @param travelPlan 旅行计划
     * @return API响应内容
     * @throws IOException API调用异常
     * @throws ParseException 解析异常
     */
    private String createRemind(TravelPlan travelPlan) throws IOException, ParseException {
        log.info("开始为旅行计划[{}]创建提醒", travelPlan.getTitle());

        // 获取用户的偏好语言
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", travelPlan.getUsername());
        User user = userMapper.selectOne(userQueryWrapper);
        
        String language = "zh_CN"; // 默认语言
        if (user != null && user.getPreferredLanguage() != null) {
            language = user.getPreferredLanguage();
            log.info("用户[{}]偏好语言: {}", user.getUsername(), language);
        }

        // 计算今天是旅行的第几天
        LocalDate today = LocalDate.now();
        LocalDate startDate = travelPlan.getStartTime().toInstant()
                .atZone(ZoneId.systemDefault()).toLocalDate();
        long dayNumber = ChronoUnit.DAYS.between(startDate, today) + 1;

        if (dayNumber < 1) {
            dayNumber = 1; // 确保至少是第一天
        }

        log.info("今天是旅行计划[{}]的第{}天", travelPlan.getTitle(), dayNumber);

        // 构建请求参数，按照案例要求
        Map<String, Object> inputs = new HashMap<>();

        // 1. json参数 - 旅行计划的JSON
        inputs.put("json", travelPlan.getPlan());

        // 2. time参数 - 今天是旅行的第几天（转换为字符串类型）
        inputs.put("time", String.valueOf(dayNumber));

        // 3. language参数 - 用户偏好语言
        inputs.put("language", language);

        // 构建完整请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("inputs", inputs);
        requestBody.put("response_mode", "blocking");
        requestBody.put("user", travelPlan.getUsername());

        String requestUrl = apiUrl;

        // 创建HTTP请求
        HttpPost httpPost = new HttpPost(requestUrl);
        httpPost.setHeader(new BasicHeader("Authorization", "Bearer " + apiKey));
        httpPost.setHeader("Content-type", "application/json");


        // 设置请求体
        String jsonBody = requestBody.toJSONString();
        log.info("API请求体: {}", jsonBody);
        httpPost.setEntity(new StringEntity(jsonBody));

        // 发送请求并获取响应
        try (CloseableHttpClient httpClient = HttpClients.custom().build();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {

            int statusCode = response.getCode();
            HttpEntity entity = response.getEntity();
            String responseContent = EntityUtils.toString(entity, "UTF-8");
            log.info("API响应状态码: {}, 长度: {}", statusCode, responseContent.length());

            if (statusCode != 200) {
                log.error("API调用失败，状态码: {}, 响应: {}", statusCode, responseContent);
                throw new IOException("API调用失败，状态码: " + statusCode);
            }

            log.info("成功获取API响应，长度: {}", responseContent.length());
            return responseContent;
        }
    }
}
